#include <iostream>
#include<cstdio>
#include<pthread.h>
#include<unistd.h>
#include <semaphore.h>
#include <string>

class Sem
{
  private:
    sem_t sem;
  public:
    Sem(int num)
    {
      sem_init(&sem, 0, num);
    }

    void P()
    {
      sem_wait(&sem);
    }
    void V()
    {
      sem_post(&sem); //资源归还
    }
    ~Sem()
    {
      sem_destroy(&sem);
    }

};

Sem sem(1);

#define NUM 2000 
int tickets = NUM; // 临界资源 
//pthread_mutex_t mutex;

void *ticket_get(void *arg)
{
  //const char* name = (char*)arg;  
  std::string name = (char*)arg;
  sleep(1);
  while(true)
  {
    sem.P();
    //pthread_mutex_lock(&mutex);
    if(tickets > 0){
      usleep(1000);
      //printf("[%s] num ticket: %d\n", name, tickets--);//tickets--是临界区，不是原子的
      std::cout << name << " get ticket: "<< tickets-- <<std::endl;
      //pthread_mutex_unlock(&mutex);
      sem.V();
    }
    else
    {
      sem.V();
      //pthread_mutex_unlock(&mutex);
      break;
    }
  }

  //printf("%s quit!\n", name);
  std::cout << name << " quit " << std::endl;
  pthread_exit((void*)0);
}

int main()
{
  pthread_t t1, t2, t3, t4, t5, t6;
 //pthread_mutex_init(&mutex, NULL);
  pthread_create(&t1, NULL, ticket_get, (void*)"thread 1");
  pthread_create(&t2, NULL, ticket_get, (void*)"thread 2");
  pthread_create(&t3, NULL, ticket_get, (void*)"thread 3");
  pthread_create(&t4, NULL, ticket_get, (void*)"thread 4");
  pthread_create(&t5, NULL, ticket_get, (void*)"thread 5");
  pthread_create(&t6, NULL, ticket_get, (void*)"thread 6");

  // 线程等待
  pthread_join(t1, NULL);
  pthread_join(t2, NULL);
  pthread_join(t3, NULL);
  pthread_join(t4, NULL);
  pthread_join(t5, NULL);
  pthread_join(t6, NULL);

  // pthread_mutex_destroy(&mutex);
  //while(1){
  //  printf("I am main thread!,pid: %d \n",getppid());
  //  sleep(2);
  //}
  return 0;
}
